package com.codebattery.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.stereotype.Component;
import springfox.documentation.swagger.web.SwaggerResource;
import springfox.documentation.swagger.web.SwaggerResourcesProvider;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 聚合各个服务的swagger接口
 *
 * @author Eric
 * @since <pre>2019/04/09</pre>
 */
@Component
public class CustomSwaggerResourceProvider implements SwaggerResourcesProvider {
 
  /**
   * swagger2默认的url后缀
   */
  private static final String SWAGGER2URL = "/v2/api-docs";
 
  /**
   * 网关路由
   */
  private final RouteLocator routeLocator;
 
  /**
   * 网关应用名称
   */
  @Value("${spring.application.name}")
  private String self;
 
  @Autowired
  public CustomSwaggerResourceProvider(RouteLocator routeLocator) {
    this.routeLocator = routeLocator;
  }
 
  @Override
  public List<SwaggerResource> get() {
    List<SwaggerResource> resources = new ArrayList<>();
    List<String> routeHosts = new ArrayList<>();
    // 网关采用的是负载均衡的方式，因此我需要拿到所有应用的serviceId
    // 获取所有可用的host：serviceId
    routeLocator.getRoutes().filter(route -> route.getUri().getHost() != null)
        .filter(route -> !self.equals(route.getUri().getHost()))
        .subscribe(route -> routeHosts.add(route.getUri().getHost()));
 
    // 记录已经添加过的server，存在同一个应用注册了多个服务在nacos上
    Set<String> dealed = new HashSet<>();
    routeHosts.forEach(instance -> {
      // 拼接url，样式为/serviceId/v2/api-info，当网关调用这个接口时，会自动通过负载均衡寻找对应的主机
      String url = "/doc/" + instance + SWAGGER2URL;
      if (!dealed.contains(url)) {
        dealed.add(url);
        SwaggerResource swaggerResource = new SwaggerResource();
        swaggerResource.setUrl(url);
        swaggerResource.setName(instance);
        resources.add(swaggerResource);
      }
    });
    return resources;
  }
}